/*
 *  basetypes.hpp - base types and declarations
 *
 *    Copyright (c) 2001-2006, Luxena Company. All rights reserved.
 *
 *  Purpose:
 *
 */

#ifndef _BASETYPES_HPP
#define _BASETYPES_HPP

#ifndef __cplusplus
#error This header requires a C++ compiler ...
#endif

/////////////////////////////////////////////////////////////////////////////
// Platform specific definitions

#ifdef _MSC_VER
#define com_interface
#elif __GNUC__
#define __stdcall __attribute__((stdcall))
#define com_interface __attribute__((com_interface))
#endif

#define APICALLTYPE __stdcall
#define METHODCALLTYPE __stdcall

#define API(type) extern "C" type APICALLTYPE

#define METHOD(type) virtual type METHODCALLTYPE
#define METHODIMP(type) type METHODCALLTYPE


/////////////////////////////////////////////////////////////////////////////
// Base types definitions

typedef void *pVOID;
typedef int BOOL, *pBOOL;
typedef char CHAR, *pCHAR;
typedef unsigned char BYTE, *pBYTE;
typedef short int INT16, *pINT16;
typedef short unsigned int UINT16, *pUINT16;
typedef int INT32, *pINT32;
typedef unsigned int UINT32, *pUINT32;
typedef float FLOAT, *pFLOAT;
typedef double DFLOAT, *pDFLOAT;


/////////////////////////////////////////////////////////////////////////////
// SQLUnknown interface

struct SQLUnknown
{
#pragma pack(push, before_typedef, 1)
	struct GUID
	{
		UINT32 Data1;
		UINT16 Data2;
		UINT16 Data3;
		BYTE Data4[8];
	};
#pragma pack(pop, before_typedef)

	METHOD(INT32) QueryInterface (const GUID& riid, void **ppvObject) = 0;
	METHOD(UINT32) AddRef (void) = 0;
	METHOD(UINT32) Release (void) = 0;
} com_interface;


/////////////////////////////////////////////////////////////////////////////
// CUnknownImpl - SQLUnknown implementation

template <class T>
class CUnknownImpl : public T
{
public:
	CUnknownImpl (): m_cRef(1) {}
	virtual ~CUnknownImpl () {};

// SQLUnknown
public:
	METHOD(INT32) QueryInterface (const SQLUnknown::GUID& riid, void **ppvObject);

	METHOD(UINT32) AddRef ();
	METHOD(UINT32) Release ();

private:
	UINT32 m_cRef;
};

template <class T>
METHODIMP(INT32) CUnknownImpl<T>::QueryInterface (const SQLUnknown::GUID& riid, void **ppvObject)
{
	*ppvObject = static_cast<SQLUnknown*>(this);
	AddRef();
	return 0;
}

template <class T>
METHODIMP(UINT32) CUnknownImpl<T>::AddRef ()
{
	return ++m_cRef;
}

template <class T>
METHODIMP(UINT32) CUnknownImpl<T>::Release ()
{
	UINT32 l = --m_cRef;
	if (l == 0)
		delete this;
	return l;
}

#endif // _BASETYPES_HPP
